/****************************************************************************
 * Elisa 1.0                                                                *
 *--------------------------------------------------------------------------*
 * Author: Laurent Granvilliers, Vincent Sorin                              *
 * Copyright (c) 2004 Laboratoire d'Informatique de Nantes Atlantique       *
 *--------------------------------------------------------------------------*
 * Elisa is distributed WITHOUT ANY WARRANTY. Read the associated           *
 * COPYRIGHT file for more details.                                         *
 *--------------------------------------------------------------------------*
 * elisa_interval_form.h                                                    *
 ****************************************************************************/


/**
 * @file elisa_interval_form.h
 * @brief Base class for interval evaluation of expressions
 */


#ifndef _ELISA_INTERVAL_FORM_H
#define _ELISA_INTERVAL_FORM_H

#include "elisa_defs.h"
#include "elisa_real_expr.h"

NAMESPACE_ELISA

#define FORM_RTYPE Interval
//#define FORM_RTYPE const Interval&
#define CONST const
//#define CONST

/**
 * @ingroup Interval
 * @class IntervalForm
 * @brief Base class for interval evaluation of expressions
 */
class IntervalForm
{
public:
	/**
 	 * Constructor
 	 */
	IntervalForm ()
	{
	}

	/**
 	 * Destructor
 	 */
	virtual ~IntervalForm ()
	{
	}

	/**
 	 * Return the lastly computed interval evaluation
 	 */
	virtual FORM_RTYPE value() CONST = 0;

	/**
 	 * Return the interval evaluation
 	 */
	virtual FORM_RTYPE eval() CONST = 0;

	/**
 	 * Return the interval evaluation over a box
 	 */
	virtual FORM_RTYPE eval(Box *b) CONST = 0;

	/**
 	 * Return the interval evaluation
 	 * Only the sub-expressions on v are evaluated
 	 * @return an interval
 	 */
	virtual FORM_RTYPE evalLazy(const RealVarImpl & v) CONST
	{
		return this->eval();
	}

	/**
 	 * Evaluate the expression and saves each sub_term evaluation
 	 */
	virtual void evalForward() = 0;

	/**
 	 * Descend the value of the domain of the father node
 	 * @return true if the constraint is still consistent
 	 */
	virtual bool propagBackward(const Interval & i) = 0;

	/**
 	 * Evaluate the derivative in forward mode wrt. v
 	 */
	virtual FORM_RTYPE deriv(const RealVarImpl & v) CONST = 0;
};

/**
 * @ingroup Interval
 * @class IntervalFormFactory
 * @brief Base class for the construction of an interval form
 */
class IntervalFormFactory
{
public:
	/// Constructor
	IntervalFormFactory ()
	{
	}

	/// Destructor
	virtual
	~IntervalFormFactory ()
	{
	}

	/**
 	 * Construction of an interval form
 	 * @param e a RealExpr to evaluate
 	 * @return an intervaForm corresponding to e
 	 */
	virtual IntervalForm *create(const RealExpr *e) const = 0;

	/**
 	 * Construction of an interval form
 	 * @param e a RealExpr to evaluate
 	 * @param v
 	 * @return an intervaForm corresponding to e
 	 */
	virtual IntervalForm *create(const RealExpr *e,
	                             const RealVarImpl *v) const
	{
		// ishii this->create(e);
		return this->create(e);
	}
};


//--------------------------------------------------------------------------
// class IntervalFormFactoryChooser
//--------------------------------------------------------------------------


/**
 * @ingroup Expression
 * @class mapIntervalFormFactory
 * @brief map of IntervalFormFactory. The key is the concatenation of the type of the expression
 */
typedef std::map<std::string, IntervalFormFactory *, ltstr> MapIntervalFormFactory;


/**
 * @ingroup variable
 * @class IntervalFormFactoryChooser
 * @brief Class for the management of the map of IntervalFormFactory
 */
class IntervalFormFactoryChooser {
public:
	/**
 	 * @brief insert a IntervalFormFactory into the map
 	 * @param t1 the type of the expression
 	 * @param v pointer to the IntervalFormFactory
 	 */
	static void insert(std::string t1,
	                   IntervalFormFactory *c)
	{
		if (c != 0) {
			_mapIntervalFormFactory[t1] = c;
		}
	}

	/**
 	 * @brief return a IntervalFormFactory given the type of the expression
 	 * @param t1 type of the symbolic expression
 	 * @return a pointer to a IntervalFormFactory, null
 	 * if that comparator doesn't exist
 	 */
	static IntervalFormFactory *get(std::string t1)
	{
		return _mapIntervalFormFactory[t1];
	}

	/**
 	 * @brief empty the map
 	 * @post the map is empty and all IntervalFormFactory have been deleted
 	 */
	static void clear()
	{
		MapIntervalFormFactory::iterator it;
		for (it = _mapIntervalFormFactory.begin(); it != _mapIntervalFormFactory.end(); ++it) {
			delete (*it).second;
		}
	}

private:
	/**
 	 *@var map used to recover a comparator
 	 */
	static MapIntervalFormFactory _mapIntervalFormFactory;
};
END_NAMESPACE_ELISA
#endif // ELISA_INTERVAL_FORM
